package com.beiding.my.mql;

import com.beiding.my.bomapping.BoTypeMapper;
import com.beiding.my.bomapping.BoTypeMapperHolder;
import com.beiding.my.bomapping.ExpressionDetails;
import com.beiding.my.bomapping.QuoteDetails;
import com.beiding.my.mql.utils.Block;
import com.beiding.my.mql.utils.KeywordBlock;
import com.beiding.my.mql.utils.MqlUtils;
import com.beiding.my.mql.utils.Pair;
import com.google.common.base.Joiner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
public class SelectMQLCompiler extends MQLCompiler {

    @Autowired
    private BoTypeMapperHolder boTypeMapperHolder;


    @Override
    public String compile(String mql) {


        Map<String, KeywordBlock> segmentMap = getSegmentMap(mql);

        KeywordBlock selectBlock = segmentMap.get("select");
        KeywordBlock fromBlock = segmentMap.get("from");

        if (fromBlock == null || selectBlock == null) {
            throw new MqlException("错误的mql: " + mql);
        }

        String from = fromBlock.getKeywordValue();
        String select = selectBlock.getKeywordValue();


        //可能是多个类型声明
        String[] fromArr = from.split(",");

        Map<String, BoTypeMapper> typeMapperMap = new HashMap<>();

        for (String fs : fromArr) {
            fs = fs.trim();
            if (fs.equals("")) {
                throw new MqlException("错误的mql: " + mql);
            }

            String[] tn = fs.split(" +");
            if (tn.length != 2) {
                throw new MqlException("错误的mql: " + mql);
            }

            String t = tn[0].trim();
            String n = tn[1].trim();
            if (t.equals("") || n.equals("")) {
                throw new MqlException("错误的mql: " + mql);
            }

            BoTypeMapper boTypeMapper = boTypeMapperHolder.getBoTypeMapper(t);
            if (boTypeMapper == null) {
                throw new MqlException("不存在的Bo类型: " + t);
            }
            typeMapperMap.put(n, boTypeMapper);
        }

        //处理返回类型, 会有标准格式才能处理成实体

        String[] selectList = select.split(",");

        List<ExpressionDetails> expressionDetailsList = new ArrayList<>();

        boolean standard = true;

        //判断是否是标准格式
        for (String sl : selectList) {

            int i = sl.indexOf('.');

            if (i == -1 || i == sl.length() - 1) {
                standard = false;
                break;
            }

            //找到名称
            String name = sl.substring(0, i);
            BoTypeMapper mapper = typeMapperMap.get(name);
            if (mapper == null) {
                standard = false;
                break;
            }

            //空格用于判断 是否 是其他格式  例如 :  select a.name as kkk  其中已经有 as
            String e = sl.substring(i + 1);
            int b = e.indexOf(' ');
            if (b != -1) {
                standard = false;
                e = e.substring(0, b);
            }

            ExpressionDetails expressionDetails = mapper.getExpressionDetails(name, e);
            expressionDetailsList.add(expressionDetails);
        }

        //放入条件关联中
        KeywordBlock whereBlock = segmentMap.get("where");
        String whereText = null;
        if (whereBlock != null) {

            whereText = whereBlock.getKeywordValue();

            //负载的引用关系
            Set<Block> fields = MqlUtils.findFiled(whereText, typeMapperMap.keySet());

            Map<Pair, String> rep = new HashMap<>();

            for (Block field : fields) {

                String sl = field.getText();
                int i = sl.indexOf('.');
                String name = sl.substring(0, i);
                BoTypeMapper mapper = typeMapperMap.get(name);
                String e = sl.substring(i + 1);
                ExpressionDetails expressionDetails = mapper.getExpressionDetails(name, e);
                expressionDetailsList.add(expressionDetails);

                //TODO 应该仅有一个
                Map<String, String> fieldToIdMap = expressionDetails.getFieldToIdMap();

                if (fieldToIdMap.size() != 1) {
                    throw new MqlException("错误的mql(条件错误):" + mql);
                }

                for (String f : fieldToIdMap.keySet()) {
                    rep.put(field, f);
                }

            }

            //变换条件表达式
            whereText = MqlUtils.recover(whereText, rep);

        }


        Set<String> fromS = new HashSet<>();

        typeMapperMap.forEach((k, v) -> {
            fromS.add(v.getBeTable() + " " + k);
        });

        Set<String> quoteS = new HashSet<>();

        Set<String> resultS = new HashSet<>();

        if (expressionDetailsList.size() > 0) {
            for (ExpressionDetails expressionDetails : expressionDetailsList) {

                List<QuoteDetails> quoteDetails = expressionDetails.getQuoteDetails();

                for (QuoteDetails quoteDetail : quoteDetails) {

                    //引用表
                    String quoteTableStatement = quoteDetail.getQuoteTableStatement();
                    String selfStatement = quoteDetail.getSelfStatement();
                    String holderStatement = quoteDetail.getHolderStatement();
                    fromS.add(quoteDetail.getHolderTableName() + " " + holderStatement);
                    fromS.add(quoteDetail.getTargetTableName() + " " + selfStatement);
                    fromS.add(quoteDetail.getQuoteTableName() + " " + quoteTableStatement);

                    //构建引用条件
                    quoteS.add(quoteTableStatement + "." + quoteDetail.getSelfFieldColName() + " = " + selfStatement + "." + quoteDetail.getTargetIdColName());
                    quoteS.add(quoteTableStatement + "." + quoteDetail.getHolderFieldColName() + " = " + holderStatement + "." + quoteDetail.getHolderIdColName());

                }

                if (standard) {
                    Map<String, String> fieldToIdMap = expressionDetails.getFieldToIdMap();
                    fieldToIdMap.forEach((k, v) -> {
                        resultS.add(k + " as " + v);
                    });
                }

            }
        }

        Map<Pair, String> rep = new HashMap<>();

        if (resultS.size() > 0) {
            String resultString = "select " + Joiner.on(",").join(resultS)+" ";
            rep.put(selectBlock, resultString);
        }


        if (fromS.size() > 0) {
            String fromString = "from "+Joiner.on(",").join(fromS)+" ";
            rep.put(fromBlock, fromString);
        }


        //不存在条件表达式
        if (whereText == null) {
            if (quoteS.size() > 0) {
                String quoteConditionString = Joiner.on(" and ").join(quoteS);

                String s = rep.get(fromBlock);
                //追加到from块中
                rep.put(fromBlock, s + " where " + quoteConditionString + " ");
            }
        } else {

            String w = whereText;
            if (quoteS.size() > 0) {
                String quoteConditionString = Joiner.on(" and ").join(quoteS);
                w = "where (" + w + ") and " + "(" + quoteConditionString + ") ";
            }
            rep.put(whereBlock, w);
        }

        String recover = MqlUtils.recover(mql, rep);

        System.out.println(recover);
        return recover;
    }

    @Override
    public String getCommand() {
        return "select";
    }

    @Override
    public String[] segmentKeywords() {
        return new String[]{"select", "from", "where"};
    }

}
